package antempire.control.game.operation.fishoperation;

import java.util.Random;

import antempire.control.game.GameConstants;
import antempire.control.game.operation.ModelInformationController;

public class AntOperation implements GameConstants {
	final Random random = new Random();
	AntController controller;

	public void set_Controller(AntController _controller) {
		controller = _controller;
	}

	public void set_side(Move_Direction _diretion) {
		// controller.direction=_diretion;
		controller.direction = Move_Direction.LEFT;
		if (controller.direction.equals(Move_Direction.RANDOM)) {
			controller.way = Math.abs(random.nextInt()) % 4;

			switch (controller.way) {
			case 0:
				controller.X = CAMERA_WIDTH
						+ ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_width();
				break;
			case 1:
				controller.X = -1
						* ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_width();
				break;
			case 2:
				controller.Y = -1
						* ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_height();
				break;
			case 3:
				controller.Y = CAMERA_HEIGHT
						+ ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_height();
				break;
			}
		} else {
			switch (controller.direction) {
			case LEFT: {
				controller.way = 1;
				// controller.X=-1*ResourcesOperation.getInstance().getFishInformation(controller.name).get_TextureRegion_width();
				controller.X = -1
						* ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_width();
				break;
			}
			case RIGHT: {
				controller.way = 0;
				controller.X = CAMERA_WIDTH
						+ ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_width();
				break;
			}
			case UP: {
				controller.way = 2;
				// controller.X=-1*ResourcesOperation.getInstance().getFishInformation(controller.name).get_TextureRegion_width();
				controller.Y = -1
						* ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_height();
				break;
			}
			case DOWN: {
				controller.way = 3;
				controller.Y = CAMERA_HEIGHT
						+ ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_height();
				break;
			}
			}
		}
	}

	public void set_edge_position(Edge_Position _position) {
		controller.position = _position;
		if (controller.position.equals(Edge_Position.RANDOM)) {
			switch (controller.way) {
			case 0:
			case 1:
				controller.Y = Math.abs(random.nextInt()) % 5 * 100 + 100;
				break;
			case 2:
			case 3:
				controller.X = Math.abs(random.nextInt()) % 5 * 200 + 200;
				break;
			}
		} else {
			switch (controller.way) {
			case 0:
			case 1:
				switch (controller.position) {
				case TOP: {
					controller.Y = 100;
					break;
				}
				case UP: {
					controller.Y = 200;
					break;
				}
				case MIDDLE: {
					controller.Y = 300;
					break;
				}
				case DOWN: {
					controller.Y = 400;
					break;
				}
				case BOTTOM: {
					controller.Y = 500;
					break;
				}
				}
				break;
			case 2:
			case 3:
				switch (controller.position) {
				case TOP: {
					controller.X = 200;
					break;
				}
				case UP: {
					controller.X = 400;
					break;
				}
				case MIDDLE: {
					controller.X = 600;
					break;
				}
				case DOWN: {
					controller.X = 800;
					break;
				}
				case BOTTOM: {
					controller.X = 1000;
					break;
				}
				}
				break;
			}
		}
	}

	public void set_fixed_Y(int _position) {
		controller.Y = _position;
	}

	public void set_fixed_X(int _position) {
		controller.X = _position;
	}

	private void Direct_initial(int currentRotation) {
		// float
		// speed=ResourcesOperation.getInstance().getFishInformation(controller.name).get_speed();
		float speed = ModelInformationController.getInstance()
				.getAntInformation(controller.name).get_speed();

		switch (controller.way) {
		case 0: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			controller.current_rotation = currentRotation;
			controller.setRotation(controller.current_rotation);
			controller.mPhysicsHandler
					.setVelocity(
							-1
									* speed
									* (float) Math
											.cos(controller.current_rotation * 3.14 / 180),
							-1
									* speed
									* (float) Math
											.sin(controller.current_rotation * 3.14 / 180));
			break;
		}
		case 1: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			controller.current_rotation = currentRotation + 180;
			controller.setRotation(controller.current_rotation);
			// controller.mPhysicsHandler.setVelocity(speed, 0);
			controller.mPhysicsHandler
					.setVelocity(
							-1
									* speed
									* (float) Math
											.cos(controller.current_rotation * 3.14 / 180),
							-1
									* speed
									* (float) Math
											.sin(controller.current_rotation * 3.14 / 180));
			break;
		}
		case 2:
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			controller.current_rotation = currentRotation;
			controller.setRotation(controller.current_rotation);
			controller.mPhysicsHandler
					.setVelocity(
							-1
									* speed
									* (float) Math
											.cos(controller.current_rotation * 3.14 / 180),
							-1
									* speed
									* (float) Math
											.sin(controller.current_rotation * 3.14 / 180));
			break;
		case 3:
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			controller.current_rotation = currentRotation;
			controller.setRotation(controller.current_rotation);
			controller.mPhysicsHandler
					.setVelocity(
							-1
									* speed
									* (float) Math
											.cos(controller.current_rotation * 3.14 / 180),
							-1
									* speed
									* (float) Math
											.sin(controller.current_rotation * 3.14 / 180));
			break;
		}
		;
	}

	private void Curve_initial(int A) {
		switch (controller.way) {
		case 0: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			// controller.mPhysicsHandler.setVelocity(-1*ResourcesOperation.getInstance().getFishInformation(controller.name).get_speed(),0);
			controller.mPhysicsHandler.setVelocity(-1
					* ModelInformationController.getInstance()
							.getAntInformation(controller.name).get_speed(), 0);
			controller.mPhysicsHandler.setAcceleration(0, A);
			break;
		}
		case 1: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			// controller.mPhysicsHandler.setVelocity(ResourcesOperation.getInstance().getFishInformation(controller.name).get_speed(),0);
			controller.mPhysicsHandler.setVelocity(ModelInformationController
					.getInstance().getAntInformation(controller.name)
					.get_speed(), 0);
			controller.mPhysicsHandler.setAcceleration(0, A);
			break;
		}
		case 2: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			// controller.mPhysicsHandler.setVelocity(-1*ResourcesOperation.getInstance().getFishInformation(controller.name).get_speed(),0);
			controller.mPhysicsHandler.setVelocity(
					0,
					ModelInformationController.getInstance()
							.getAntInformation(controller.name).get_speed());
			controller.mPhysicsHandler.setAcceleration(A, 0);
			break;
		}
		case 3: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			// controller.mPhysicsHandler.setVelocity(ResourcesOperation.getInstance().getFishInformation(controller.name).get_speed(),0);
			controller.mPhysicsHandler.setVelocity(0, -1
					* ModelInformationController.getInstance()
							.getAntInformation(controller.name).get_speed());
			controller.mPhysicsHandler.setAcceleration(A, 0);
			break;
		}
		}
		;
	}

	private void Circle_initial() {
		switch (controller.way) {
		case 0: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			controller.mPhysicsHandler.setVelocity(-80, 0);
			controller.mPhysicsHandler.setAngularVelocity(0);
			// controller.setRotation(0);

			break;
		}
		case 1: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			controller.mPhysicsHandler.setVelocity(80, 0);
			controller.mPhysicsHandler.setAngularVelocity(0);
			// controller.setRotation(180);

			break;
		}
		case 2: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			controller.mPhysicsHandler.setVelocity(0, 80);
			controller.mPhysicsHandler.setAngularVelocity(0);
			// controller.setRotation(0);

			break;
		}
		case 3: {
			controller.setPosition(controller.X, controller.Y);
			controller.current_X = controller.X;
			controller.current_Y = controller.Y;
			controller.mPhysicsHandler.setVelocity(0, -80);
			controller.mPhysicsHandler.setAngularVelocity(0);
			// controller.setRotation(180);

			break;
		}
		}
		;
	}

	public void set_Direct_Move(int rotation) {
		controller.move = Ant_Move.Direct;
		Direct_initial(rotation);
	}

	public void set_Curve_Move(int acceleration) {
		controller.move = Ant_Move.Curve;
		Curve_initial(acceleration);
	}

	public void set_Circle_Move() {
		controller.move = Ant_Move.Circle;
		Circle_initial();
	}

	public void set_Move(Ant_Move move) {
		if (move.equals(Ant_Move.Random)) {
			int i = Math.abs(random.nextInt()) % 2;
			switch (i) {
			case 0: {
				move = Ant_Move.Direct;
				break;
			}
			case 1: {
				move = Ant_Move.Curve;
				break;
			}
			}
		}
		switch (move) {
		case Direct: {
			int rotation = Math.abs(random.nextInt()) % 30 + 1;
			set_Direct_Move(rotation);
			break;
		}
		case Curve: {
			int a = -1 * (Math.abs(random.nextInt()) % 25 + 1);
			set_Curve_Move(a);
			break;
		}
		case Circle: {
			set_Circle_Move();
			break;
		}
		}
	}

	public boolean isOutOfBound() {
		if (controller.getX() >= CAMERA_WIDTH
				||
				// controller.getX()<-1*ResourcesOperation.getInstance().getFishInformation(controller.name).get_TextureRegion_width()
				// || controller.getY()>=CAMERA_WIDTH||
				// controller.getY()<-1*ResourcesOperation.getInstance().getFishInformation(controller.name).get_TextureRegion_width())
				controller.getX() < -1
						* ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_width()
				|| controller.getY() >= CAMERA_WIDTH
				|| controller.getY() < -1
						* ModelInformationController.getInstance()
								.getAntInformation(controller.name)
								.get_TextureRegion_width())

		{
			return true;
		} else
			return false;
	}

	public void fishOnManagedUpdate() {
		float x = controller.getX();
		float y = controller.getY();
		float rotation = controller.getRotation();
		Random random = new Random();

		if (controller.move.equals(Ant_Move.Direct)) {
			if (isOutOfBound()) {

			}
		} else if (controller.move.equals(Ant_Move.Curve)) {
			if (!isOutOfBound()) {
				switch (controller.way) {
				case 0: {
					rotation = (float) ((Math.atan((y - controller.current_Y)
							/ (x - controller.current_X))) * 180 / 3.14);
					if (!isInSameRange(controller.getCurrentTileIndex(),
							rotation)) {
						controller.setRotation(rotation);
					}
					break;
				}
				case 1: {
					rotation = (float) (180 + (Math
							.atan((y - controller.current_Y)
									/ (x - controller.current_X))) * 180 / 3.14);
					if (!isInSameRange(controller.getCurrentTileIndex(),
							rotation)) {
						controller.setRotation(rotation);
					}
					break;
				}
				}
				;
			}
		} else if (controller.move.equals(Ant_Move.Circle)) {
			switch (controller.way) {
			case 0: {
				if (rotation >= 360) {
					// controller.mPhysicsHandler.setAngularVelocity(0);
					// controller.mPhysicsHandler.setVelocity(-80, 0);
					if (!isInSameRange(controller.getCurrentTileIndex(), 360)) {
						controller.setRotation(360);
					}
				} else if (x < (CAMERA_WIDTH / 2)
						|| (x > (CAMERA_WIDTH / 2) && y < controller.Y)) {
					controller.mPhysicsHandler.setAngularVelocity(85);
					controller.mPhysicsHandler.setVelocity(
							-1 * (float) Math.cos(rotation * 3.14 / 180) * 80,
							-1 * (float) Math.sin(rotation * 3.14 / 180) * 80);
				}

				break;
			}
			case 1: {
				if (x > (CAMERA_WIDTH / 5)
						|| (x < (CAMERA_WIDTH / 2) && y < controller.Y)) {
					// controller.mPhysicsHandler.setAngularVelocity(275);
					rotation = (float) (180 + (Math
							.atan((y - controller.current_Y)
									/ (x - controller.current_X))) * 180 / 3.14);
					if (!isInSameRange(controller.getCurrentTileIndex(),
							rotation)) {
						controller.setRotation(rotation);
					}
					controller.mPhysicsHandler.setAcceleration(
							(float) random.nextGaussian() * 20,
							(float) random.nextGaussian() * 20);
				}

				break;
			}
			}
			;

		}
		controller.current_rotation = rotation;
		controller.current_X = x;
		controller.current_Y = y;
	}

	private boolean isInSameRange(int a, float b) {
		if (a >= 9 && a <= 11 && b % 360 >= -45 && b % 360 <= 45) {
			return true;
		}
		if (a >= 0 && a <= 2 && b % 360 > 45 && b % 360 <= 135) {
			return true;
		}
		if (a >= 3 && a <= 5 && b % 360 > 135 && b % 360 <= 225) {
			return true;
		}
		if (a >= 6 && a <= 8 && b % 360 > 225 && b % 360 <= 315) {
			return true;
		}
		if (a >= 9 && a <= 11 && b % 360 > 315 && b % 360 <= 405) {
			return true;
		}
		return false;
	}
}
